package com.alibaba.citrus.ots.price.ability.facade;

import com.alibaba.acm.shaded.com.google.common.collect.Lists;
import com.alibaba.acm.shaded.com.google.common.collect.Maps;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.util.MD5Utils;
import com.alibaba.citrus.ots.price.ability.functions.entity.price.PriceDimensionConfigEntity;
import com.alibaba.citrus.ots.price.ability.functions.entity.price.PriceDimensionRuleEntity;
import com.alibaba.citrus.ots.price.ability.functions.factory.price.PriceDimensionConfigFactory;
import com.alibaba.citrus.ots.price.ability.functions.factory.price.PriceDimensionRuleFactory;
import com.alibaba.citrus.ots.price.ability.functions.factory.price.process.PriceProcess;
import com.alibaba.citrus.ots.price.ability.functions.factory.price.process.PropertyProcessManager;
import com.alibaba.citrus.ots.price.repository.PriceQueryRepository;
import com.alibaba.citrus.ots.price.repository.PriceWriteRepository;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorCodeException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.otspricecenter.api.pricewrite.service.PriceWriteService;
import com.epoch.app.otspricecenter.dto.request.CreatePriceDimensionRequest;
import com.epoch.app.otspricecenter.dto.request.ModifyPriceDimensionRequest;
import com.epoch.app.otspricecenter.dto.request.SyncPriceDataRequest;
import com.epoch.app.otspricecenter.dto.request.SyncPriceDimensionConfigDataRequest;
import com.epoch.app.otspricecenter.dto.request.SyncPriceTypeRequest;
import com.epoch.app.otspricecenter.dto.response.CreatePriceDimensionResponse;
import com.epoch.app.otspricecenter.dto.response.ModifyPriceDimensionResponse;
import com.epoch.app.otspricecenter.dto.response.SyncPriceDataResponse;
import com.epoch.app.otspricecenter.dto.response.SyncPriceDimensionDataResponse;
import com.epoch.app.otspricecenter.dto.response.SyncPriceTypeResponse;
import com.epoch.app.otspricecenter.enums.DimensionPropertyEnum;
import com.epoch.app.otspricecenter.model.dto.PriceIdLis;
import com.epoch.app.otspricecenter.sdo.PriceDimensionConfigSDO;
import com.epoch.app.otspricecenter.sdo.PriceDimensionSDO;
import com.epoch.app.otspricecenter.sdo.PriceRecordSDO;
import com.epoch.app.otspricecenter.sdo.PriceTypeSDO;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @author: qiaojiange
 * @create: 2021/09/16
 * @Description 价格写入服务
 */
@Service
public class PriceWriteServiceImpl implements PriceWriteService {

    private Log log = Log.getLogger(PriceWriteServiceImpl.class);

    private static final String MESSAGE_ID = "messageId";

    private static final String DATA_SOURCE = "dataSource";

    private static final String priceUniteDesc = "price_unite_desc";

    @Resource
    private PriceQueryRepository priceQueryRepository;

    @Resource
    private PriceWriteRepository priceWriteRepository;

    @Resource
    private PropertyProcessManager propertyProcessManager;

    @FacadeInvoker(value = "同步价格类型数据", errorCode = "OTS-07-005-01-15-003")
    @Override
    public Result<SyncPriceTypeResponse> syncPriceTypeData(SyncPriceTypeRequest request) {
        SyncPriceTypeResponse syncPriceTypeResponse = new SyncPriceTypeResponse();
        if (StringUtils.isEmpty(request.getPriceTypeId())) {
            throw new FacadeException("OTS-07-005-01-15-007");
        }
        PriceTypeSDO priceTypeSDO = new PriceTypeSDO();
        BeanUtils.copyProperties(request, priceTypeSDO);
        Boolean booleanResult = priceWriteRepository.createPriceTypeData(priceTypeSDO);
        syncPriceTypeResponse.setSucceeded(booleanResult);
        syncPriceTypeResponse.setResponseMsg("同步数据成功");
        syncPriceTypeResponse.setResponseCode("SYNC_DATA_SUCCEED");
        return Result.success(syncPriceTypeResponse);
    }

    @Override
    @FacadeInvoker(value = "同步价格属性配置数据", errorCode = "OTS-07-005-01-15-008")
    public Result<SyncPriceDimensionDataResponse> syncPricePropertyConfigData(SyncPriceDimensionConfigDataRequest request) {
        checkParam(request);
        PriceDimensionConfigEntity dimensionConfigEntity = PriceDimensionConfigFactory.create(request);
        //不影响保存逻辑
        try {
            obtainPropertyDesc(dimensionConfigEntity.getPriceDimensionConfigSDO());
        } catch (Exception e) {
           log.error("字段冗余时出现问题 请排查 :",e);
        }
        boolean result = dimensionConfigEntity.save();
        if(!result){
            log.error("PriceWriteServiceImpl.syncPricePropertyConfigData_fail");
        }
        SyncPriceDimensionDataResponse response = new SyncPriceDimensionDataResponse();
        response.setSucceeded(result);
        return Result.success(response);
    }

    /**
     * 价格配置表里存入冗余数据
     * @param priceDimensionConfigSDO
     */
    @FacadeInvoker(value = "价格配置数据冗余处理")
    private void obtainPropertyDesc(PriceDimensionConfigSDO priceDimensionConfigSDO) {
        Map<String, String> featuresMap = priceDimensionConfigSDO.getFeaturesMap();
        featuresMap.entrySet().forEach(e -> {
            String propertyKey = e.getKey();
            PriceProcess priceProcess = propertyProcessManager.getPropertyProcess(propertyKey);
            if (Objects.nonNull(priceProcess)) {
                Map<String, String> codeAndDescMap = priceProcess.obtainCodeAndDescMap(Lists.newArrayList(e.getValue()), false);
                if (MapUtils.isNotEmpty(codeAndDescMap)) {
                    String propertyName = codeAndDescMap.get(e.getValue());
                    if (StringUtils.isNotBlank(propertyName)) {
                        featuresMap.put(propertyKey, propertyName);
                    } else {
                        featuresMap.put(propertyKey, null);
                    }
                } else {
                    featuresMap.put(propertyKey, null);
                }
            }

        });
    }


    /**
     * 参数校验
     *
     * @param request
     */
    private void checkParam(SyncPriceDimensionConfigDataRequest request) {
        if (Objects.isNull(request)) {
            throw new FacadeException("参数为空！！！", request);
        }
        if (CollectionUtils.isEmpty(request.getDimensionPropertyList())) {
            throw new FacadeException("属性列表为空！不能保存！", request);
        }
        if (StringUtils.isBlank(request.getDimensionId()) && StringUtils.isBlank(request.getTableName())) {
            throw new FacadeException("维度 ID 和 维度表名不能同时为空！", request);
        }
    }

    @FacadeInvoker(remark = "同步价格记录数据")
    @Override
    public Result<SyncPriceDataResponse> syncPriceRecordData(SyncPriceDataRequest request) {

        SyncPriceDataResponse syncPriceDataResponse = new SyncPriceDataResponse();

        if (StringUtils.isEmpty(request.getPriceRecordId())) {
            syncPriceDataResponse.setSucceeded(false);
            syncPriceDataResponse.setResponseCode("PRICE-RECORD-ID-MUST-NOT-NULL");
            syncPriceDataResponse.setResponseMsg("价格记录ID不允许为空");
            return Result.fail(syncPriceDataResponse, null, null);
        }

        //不存在则新增
        PriceRecordSDO priceRecordSDO = new PriceRecordSDO();
        BeanUtils.copyProperties(request, priceRecordSDO);
        Map<String,String> features = Maps.newHashMap();
        features.put(MESSAGE_ID,request.getMessageId());
        features.put(DATA_SOURCE,request.getDataSource());
        Map<String, String> saleUnitCodeAndDesc = propertyProcessManager.getPropertyProcess(DimensionPropertyEnum.SALES_UNIT_CODE.getKey()).obtainCodeAndDescMap(Lists.newArrayList(priceRecordSDO.getPriceUnite()), true);
        features.put(priceUniteDesc,saleUnitCodeAndDesc.get(priceRecordSDO.getPriceUnite()));
        priceRecordSDO.setFeatures(JSONObject.toJSONString(features));
        if (Objects.isNull(priceRecordSDO.getStatus())) {
            priceRecordSDO.setStatus(1);
        }
        Result<Boolean> booleanResult = new Result<>();
        booleanResult.setResult(priceWriteRepository.createPriceRecordData(priceRecordSDO).getResult());
        syncPriceDataResponse.setSucceeded(booleanResult.getResult());
        if(!booleanResult.getResult()){
            log.error("PriceWriteServiceImpl#syncPriceRecordData_fail");
        }
        if (booleanResult.getResult()) {
            syncPriceDataResponse.setResponseMsg("同步数据成功");
            syncPriceDataResponse.setResponseCode("SYNC_DATA_SUCCEED");
        } else {
            syncPriceDataResponse.setResponseMsg(booleanResult.getMessage());
            syncPriceDataResponse.setResponseCode(booleanResult.getErrorCode());
        }
        return Result.success(syncPriceDataResponse);

    }

    @Override
    public Result<CreatePriceDimensionResponse> createPriceDimension(CreatePriceDimensionRequest createPriceDimensionRequest) {
        //非被动接口，供后台维度配置页面调用

        CreatePriceDimensionResponse createPriceDimensionResponse = new CreatePriceDimensionResponse();

        if (StringUtils.isEmpty(createPriceDimensionRequest.getDimensionId())) {
            createPriceDimensionResponse.setSucceeded(false);
            createPriceDimensionResponse.setResponseCode("PRICE-DIMENSION-ID-MUST-NOT-NULL");
            createPriceDimensionResponse.setResponseMsg("价格维度ID不允许为空");
            return Result.fail(createPriceDimensionResponse, null, null);
        }
        //根据dimensionId获取维度数据
//        Result<PriceDimensionSDO> priceDimensionSDOResult = priceQueryRepository.queryPriceDimension(createPriceDimensionRequest.getDimensionId());
//
//        //不存在则新增
        try {
            PriceDimensionSDO priceDimensionSDO = new PriceDimensionSDO();
            BeanUtils.copyProperties(createPriceDimensionRequest, priceDimensionSDO);
            Result<Boolean> priceDimensionData = new Result<>();
            priceDimensionData.setResult(priceWriteRepository.createPriceDimensionData(priceDimensionSDO).getResult());
            createPriceDimensionResponse.setSucceeded(priceDimensionData.getResult());
            if (priceDimensionData.getResult()) {
                createPriceDimensionResponse.setResponseMsg("同步数据成功");
                createPriceDimensionResponse.setResponseCode("SYNC_DATA_SUCCEED");
            } else {
                createPriceDimensionResponse.setResponseMsg(priceDimensionData.getMessage());
                createPriceDimensionResponse.setResponseCode(priceDimensionData.getErrorCode());
            }
            return Result.success(createPriceDimensionResponse);
        } catch (ErrorCodeException e) {
            throw e;
        } catch (Exception e) {
            log.error("同步价格维度数据出错！！！", e);
            throw new FacadeException("OTS-07-005-01-15-004");
        }
    }

    //todo 韩国 9月 24日
    @Override
    public Result<ModifyPriceDimensionResponse> modifyPriceDimension(ModifyPriceDimensionRequest modifyPriceDimensionRequest) {
        //非被动接口，供后台页面调用
        //根据dimensionId修改
        {
            //todo...韩国 修改逻辑后面再调整
        }
        PriceDimensionSDO priceDimensionSDO = new PriceDimensionSDO();
        BeanUtils.copyProperties(modifyPriceDimensionRequest, priceDimensionSDO);
        Result<Boolean> booleanResult = new Result<>();
        booleanResult.setResult(priceWriteRepository.modifyPriceDimension(priceDimensionSDO).getResult());
        ModifyPriceDimensionResponse modifyPriceDimensionResponse = new ModifyPriceDimensionResponse();
        modifyPriceDimensionResponse.setSucceeded(booleanResult.getResult());
        if (booleanResult.getResult()) {
            modifyPriceDimensionResponse.setResponseMsg("同步数据成功");
            modifyPriceDimensionResponse.setResponseCode("SYNC_DATA_SUCCEED");
        } else {
            modifyPriceDimensionResponse.setResponseMsg(booleanResult.getMessage());
            modifyPriceDimensionResponse.setResponseCode(booleanResult.getErrorCode());
        }
        return Result.success(modifyPriceDimensionResponse);
    }


    /**
     * 批量修改维度属性组和md5值
     * @param priceIdLis
     * @return
     */
    @FacadeInvoker
    @Override
    public Result<Void> modifyPriceDate(PriceIdLis priceIdLis) {


        //1. 根据ID查询价格数据
        //2. 分割属性维度字符串 ---》韩国
        //3. 清除头部 0 ---》韩国
        //4. 根据维度ID，属性编码，生成新的字符串---》峥嵘
        //5. 更新到库里
        if (Objects.isNull(priceIdLis) || CollectionUtils.isEmpty(priceIdLis.getIdList())) {
            return Result.success(null);
        }
        for (Long id : priceIdLis.getIdList()) {
            PriceDimensionConfigSDO sdo = new PriceDimensionConfigSDO();
            sdo.setId(id);
            PriceDimensionConfigSDO oldSDO = priceQueryRepository.loadById(sdo.getId());
            log.info("oldSDO: ", oldSDO);
            Map<String, String> map = splitProperty(oldSDO.getDimensionPropertiesGroup());

            PriceDimensionConfigSDO newSDO = new PriceDimensionConfigSDO();
            BeanUtils.copyProperties(oldSDO, newSDO);
            newSDO.setDimensionPropertiesGroup(produceNewPropertiesGroup(oldSDO.getDimensionId(), map));
            newSDO.setItemId(removeZeroOfHead(oldSDO.getItemId()));
            newSDO.setMd5Code(MD5Utils.encrypt32(newSDO.getDimensionPropertiesGroup()));
            log.info("newSDO:", newSDO);
            priceWriteRepository.updatePriceDimensionConfigTemp(newSDO.getId(),newSDO);
        }
        return Result.success(null);
    }

    /**
     * 修正价格扩展字段的冗余数据
     * @param priceIdLis
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Void> modifyPriceFeatures(PriceIdLis priceIdLis) {

        if (Objects.isNull(priceIdLis) || CollectionUtils.isEmpty(priceIdLis.getIdList())) {
            throw new FacadeException("请传数据");
        }
        //填充之前features里面应该冗余的数据
            for (Long id : priceIdLis.getIdList()) {
                PriceDimensionConfigSDO sdo = new PriceDimensionConfigSDO();
                sdo.setId(id);
                PriceDimensionConfigSDO oldSDO = priceQueryRepository.loadById(sdo.getId());

                if(Objects.isNull(oldSDO)){
                    continue;
                }
                log.info("oldSDO: ", oldSDO);
                Map<String, String> oldMap = splitProperty(oldSDO.getDimensionPropertiesGroup());
                Map<String, String> newMap = Maps.newHashMap();

                oldMap.entrySet().forEach(e->{
                    PriceProcess priceProcess = propertyProcessManager.getPropertyProcess(e.getKey());
                    if (Objects.nonNull(priceProcess)) {
                        Map<String, String> codeAndDescMap = priceProcess.obtainCodeAndDescMap(Lists.newArrayList(e.getValue()), false);
                        if (MapUtils.isNotEmpty(codeAndDescMap)) {
                            newMap.put(e.getKey(), codeAndDescMap.get(e.getValue()));
                        }
                    } else {
                        newMap.put(e.getKey(), e.getValue());
                    }
                    newMap.put(e.getKey()+"_flag",e.getValue());
                });
                newMap.put(DimensionPropertyEnum.ORG_SALES_ORGANIZATION_CODE.getKey()+"_flag",oldMap.get(DimensionPropertyEnum.ORG_SALES_ORGANIZATION_CODE.getKey()));
                newMap.put(DimensionPropertyEnum.CHANNEL_CODE.getKey()+"_flag",oldMap.get(DimensionPropertyEnum.CHANNEL_CODE.getKey()));
                log.info("本次更新的features字段数据结果为：{}", JSONObject.toJSONString(newMap));
                Boolean updateResult = priceWriteRepository.updatePriceDimensionConfigFeaturesTemp(id, newMap,oldSDO.getVersion());
                log.info("本次数据" + id + "更新结果：{}", updateResult);
            }

            return Result.success(null);
    }

    /**
     * 批量修改价格可用的结束时间 00:00:00-->23:59:59
     * @param priceIdLis
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Void> batchModifyPriceEndDate(PriceIdLis priceIdLis) {

        if (Objects.isNull(priceIdLis) || CollectionUtils.isEmpty(priceIdLis.getIdList())) {
            throw new FacadeException("清传数据");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (Long id : priceIdLis.getIdList()) {
            PriceDimensionConfigSDO sdo = new PriceDimensionConfigSDO();
            sdo.setId(id);
            PriceDimensionConfigSDO oldSDO = priceQueryRepository.loadById(sdo.getId());

            if (Objects.isNull(oldSDO)) {
                continue;
            }
            log.info("oldSDO: ", oldSDO);
            Date odPriceEndDate = oldSDO.getPriceEndDate();
            String format = sdf.format(odPriceEndDate);
            String newPriceEndDateStr = format.split(" ")[0] + " 23:59:59";
            try {
                Date newPriceEndDate = sdf.parse(newPriceEndDateStr);
                Boolean updateResult = priceWriteRepository.updatePriceDimensionConfigEndDateTemp(id, newPriceEndDate, oldSDO.getVersion());
                log.info("本次数据" + id + "更新结果：{}", updateResult);
            } catch (ParseException e) {
                log.error("时间解析异常", e);
            }

        }
        return Result.success(null);
    }

    /**
     * @param dimensionId
     * @param map
     * @return
     */
    private String produceNewPropertiesGroup(String dimensionId, Map<String, String> map) {
        PriceDimensionRuleEntity priceDimensionRuleEntity = PriceDimensionRuleFactory.create(dimensionId);
        String dimensionPropertyGroup = newPropertiesGrop(priceDimensionRuleEntity.getPriceDimensionSDO().getDimensionRule(), map);
        return dimensionPropertyGroup;
    }

    @Resource
    private ExpressRunner expressRunner;

    private String newPropertiesGrop(String dimensionRule, Map<String, String> map) {
        log.error("dimensionRule: ", dimensionRule);
        log.error("属性数据：", map);

//        1. 构建上下文 context；
//        2. 获取运行规则
//        3. 执行规则获取属性组字符串
//        4. 对属性组字符串进行MD5编码，并返回
        IExpressContext<String, Object> context = new DefaultContext();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            context.put(entry.getKey(), entry.getValue());
        }

        //根据规则表达式，运行计算规则，拼接字符串
        String dimensionPropertyGroup = null;
        try {
            dimensionPropertyGroup = (String) expressRunner.execute(dimensionRule, context, null, true, true);
        } catch (Exception e) {
            //todo qjg 需要确定下
            log.error("PriceWriteServiceImpl#newPropertiesGrop_fail");
            log.error("----表达式执行异常---" + dimensionPropertyGroup, e);
        }
        return dimensionPropertyGroup;

    }


    private Map<String, String> splitProperty(String dimensionPropertiesGroup) {
        if (StringUtils.isBlank(dimensionPropertiesGroup) || StringUtils.isBlank(dimensionPropertiesGroup)) {
            throw new RuntimeException("维度属性组不能为空");
        }
        Map<String, String> map = Maps.newHashMap();
        String[] dimensionRuleArr = dimensionPropertiesGroup.split(",");
        for (String dimension : dimensionRuleArr) {
            int index = dimension.lastIndexOf("_");
            String propertyKey = dimension.substring(0, index);
            String propertyValue = dimension.substring(index + 1);
            map.put(propertyKey, removeZeroOfHead(propertyValue));
        }
        log.info("处理后的结果 = {}", map);

        return map;
    }

    private String removeZeroOfHead(String s) {
        if (StringUtils.isBlank(s)) {
            return null;
        }
        String[] split = s.split("");
        String substring = null;
        for (int i = 0; i < split.length; i++) {
            if (!"0".equals(split[i])) {
                substring = s.substring(i);
                break;
            }
        }
        return substring;
    }
}
